public class Test {
    private static int count = 0;
    // synchronized 语法只接受引用类型（Object 或其子类）作为锁对象，不能使用基本类型（如 int、char 等）。
    private static final Object lock = new Object();

    public static void main(String[] args) throws Exception {
        var add = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 10000; i++) {
                    synchronized (lock) {
                        count += 1;

                    }
                }
            }
        };
        var dec = new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 10000; i++) {
                    synchronized (lock) {
                        count = count - 1;
                    }
                }
            }
        };
        add.start();
        dec.start();
        add.join();
        dec.join();
        System.out.println(count);
    }
}

// 不需要synchronized的操作
// JVM规范定义了几种原子操作：
// 基本类型（long和double除外）赋值，例如：int n = m；
// 引用类型赋值，例如：List<String> list = anotherList

// 但是，如果是多行赋值语句，就必须保证是同步操作

// java多线程不可变对象无需同步
// 不可变 = 创建后状态冻结；
// 因此读操作无竞态条件，多线程场景下天然线程安全，根本无需同步。

// 锁的是当前对象实例 (this)
// public synchronized void method() { ... }

// 锁的是当前类的 Class 对象 (Xxx.class)
// public static synchronized void staticMethod() { ... }